package com.sunchp.nio.sample.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NioServer {
    private ExecutorService executorService;
    private Selector selector;
    private ServerSocketChannel serverSocketChannel;

    public NioServer(ExecutorService executorService) {
        this.executorService = executorService;
    }

    public void serve() {
        try {
            this.selector = Selector.open();
            this.serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress(8080));
            this.serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            while (true) {
                int count = this.selector.select();
                if (count > 0) {
                    Set<SelectionKey> selectionKeys = this.selector.selectedKeys();

                    for (SelectionKey selectionKey : selectionKeys) {
                        if (selectionKey.isAcceptable()) {
                            ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                            SocketChannel socketChannel = serverSocketChannel.accept();
                            socketChannel.configureBlocking(false);
                            socketChannel.register(this.selector, SelectionKey.OP_READ);
                        }

                        if (selectionKey.isReadable()) {
                            SocketChannel sc = (SocketChannel) selectionKey.channel();
                            ByteBuffer buffer = ByteBuffer.allocate(1024);
                            buffer.clear();
                            int byteRead = sc.read(buffer);
                            System.out.println(byteRead);

                            if (byteRead == -1) {
                                System.out.println("client close connect");
                                sc.close();
                                selectionKey.cancel();
                                continue;
                            }

                            buffer.flip();
                            while (buffer.hasRemaining()) {
                                sc.write(buffer);
                            }
                        }
                    }

                    selectionKeys.clear();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new NioServer(Executors.newFixedThreadPool(4)).serve();
    }
}
